from rest_framework import serializers
from django.contrib.auth import get_user_model, authenticate
from rest_framework_simplejwt.tokens import RefreshToken
from django_redis import get_redis_connection

User = get_user_model()


class UserInfoSerializer(serializers.ModelSerializer):
    roles = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = ['id', 'username', 'email', 'phone', 'roles']

    def get_roles(self, obj):
        # 返回固定的角色列表
        return ['ALL_ROUTERS']


class LoginSerializer(serializers.Serializer):
    username = serializers.CharField(required=False, allow_blank=True)
    password = serializers.CharField(write_only=True, required=False, allow_blank=True)
    phone = serializers.CharField(required=False, allow_blank=True)
    verify_code = serializers.CharField(write_only=True, required=False, allow_blank=True)

    def validate(self, attrs):
        username = attrs.get('username')
        password = attrs.get('password')
        phone = attrs.get('phone')
        verify_code = attrs.get('verify_code')

        user = None

        if username and password:
            user = authenticate(username=username, password=password)
            if not user:
                raise serializers.ValidationError("账号或密码不正确")
        elif phone and verify_code:
            redis_conn = get_redis_connection("verify_code")
            cached_code = redis_conn.get(f"verify_code_{phone}")
            if not cached_code:
                raise serializers.ValidationError("验证码已过期或未发送")
            if verify_code != cached_code.decode('utf-8'):
                raise serializers.ValidationError("验证码错误")
            try:
                user = User.objects.get(phone=phone)
            except User.DoesNotExist:
                raise serializers.ValidationError("用户不存在")
        else:
            raise serializers.ValidationError("必须提供账号密码或手机号验证码进行登录")

        attrs['user'] = user
        return attrs

    def create(self, validated_data):
        user = validated_data['user']
        refresh = RefreshToken.for_user(user)
        return {
            'refresh': str(refresh),
            'access': str(refresh.access_token),
        }


class LogoutSerializer(serializers.Serializer):
    refresh = serializers.CharField()

    def validate(self, attrs):
        self.token = attrs['refresh']
        return attrs

    def save(self, **kwargs):
        try:
            token = RefreshToken(self.token)
            token.blacklist()
        except Exception as e:
            self.fail('bad_token')


class RegisterSerializer(serializers.ModelSerializer):
    confirm_password = serializers.CharField(write_only=True, required=True)
    verify_code = serializers.CharField(write_only=True, required=True)

    class Meta:
        model = User
        fields = ('username', 'password', 'confirm_password', 'email', 'phone', 'verify_code')
        extra_kwargs = {
            'password': {'write_only': True},
            'email': {'required': True},
            'phone': {'required': True},
        }

    def validate(self, attrs):
        if attrs['password'] != attrs['confirm_password']:
            raise serializers.ValidationError({"password": "两次密码输入不一致"})
        return attrs

    def validate_phone(self, value):
        if User.objects.filter(phone=value).exists():
            raise serializers.ValidationError("手机号已注册")
        return value

    def create(self, validated_data):
        validated_data.pop('confirm_password')
        validated_data.pop('verify_code')
        user = User.objects.create_user(
            username=validated_data['username'],
            password=validated_data['password'],
            email=validated_data['email'],
            phone=validated_data['phone']
        )
        return user
